package cloud.xiangyixiang.www.spring.boot.java.basics.controller;

import cloud.xiangyixiang.www.spring.boot.java.basics.pojo.bo.UserPredicate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * JAVA Predicate
 * </p>
 *
 * @author zhixinglu
 * @date 2023/9/21 10:55
 */
public class PredicateController {

    public static Map<String, Object> hashMap = new HashMap<>();


    public static void main(String[] args) {
        test1();

        test2();

        test3();

        test4();

        test5();

        test6();

    }

    /**
     *  ?主要用于变量上，T主要用于类或方法上
     * @param param
     * @param <T>
     * @return
     */
    private static <T> Predicate<T> getDistinct(Function<? super T, ?> param) {
        Map<Object, Boolean> map = new HashMap<>();
        // hash中不存在这个key，则返回null，如果存在返回true
        return t -> map.putIfAbsent(param.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 去掉相同key的数据
     */
    private static void test1() {
        List<UserPredicate> list = new ArrayList<>();
        list.add(new UserPredicate("zs", 18));
        list.add(new UserPredicate("ls", 28));
        list.add(new UserPredicate("ww", 38));
        list.add(new UserPredicate("ww", 40));
        System.out.println(list);
        System.out.println("----------------stream().filter-------------------------");
        List<UserPredicate> list1  = list.stream().filter(getDistinct(a -> a.getUsername())).collect(Collectors.toList());
        System.out.println(list1);
        System.out.println();
    }

    /**
     * 利用函数式接口进行比较
     */
    private static void test2(){
        Predicate<String> predicate = "zs"::equals;
        boolean test = predicate.test("ls");
        System.out.println(test);
        boolean test2 = predicate.test("zs");
        System.out.println(test2);
        System.out.println();
    }

    /**
     * 普通写法
     */
    private static void test3() {
        boolean judgeLength = judgeLength("zhangsan");
        System.out.println(judgeLength);
        boolean judgeInt = judgeInt(10);
        System.out.println(judgeInt);
        hashMap.put("zs", 18);
        hashMap.put("ls", 28);
        hashMap.put("ww", 38);
        boolean judgeKey = judgeKey("zs");
        System.out.println(judgeKey);
        System.out.println();
    }

    /**
     * 判断传入的字符串的长度是否大于5
     * @param str {@link String}
     * @return boolean
     */
    private static boolean judgeLength(String str) {
        return str.length() > 5;
    }

    /**
     * 判断传入的数字是否大于0
     * @param i {@link int}
     * @return boolean
     */
    private static boolean judgeInt(int i) {
        return i > 0;
    }

    /**
     * 判断传入的值在hash中是否存在
     * @param key {@link String}
     * @return boolean
     */
    private static boolean judgeKey(String key) {
        return hashMap.containsKey(key);
    }

    private static <T> boolean judgeByPredicate(T t, Predicate<T> predicate) {
        return predicate.test(t);
    }

    /**
     * Predicate写法
     */
    private static void test4() {
        boolean judgeByPredicate = judgeByPredicate("zhangsan", t -> t.length() > 5);
        System.out.println(judgeByPredicate);

        boolean judgeByPredicate2 = judgeByPredicate(10,t -> t > 0);
        System.out.println(judgeByPredicate2);

        hashMap.put("zs", 18);
        hashMap.put("ls", 28);
        hashMap.put("ww", 38);

        boolean judgeByPredicate3 = judgeByPredicate("zs1", t -> hashMap.containsKey(t));
        System.out.println(judgeByPredicate3);
        System.out.println();
    }

    /**
     * negate --> 取反 (逻辑非)
     * @param t
     * @param predicate
     * @param <T>
     * @return
     */
    private static <T> boolean judgeByPredicateNegate(T t, Predicate<T> predicate) {
        return predicate.negate().test(t);
    }

    /**
     * 理论上and可以无限加下去
     * @param <T>
     * @param t 待判断的参数
     * @param predicate1 断定表达式1
     * @param predicate2 断定表达式2
     * @return 是否满足两个条件
     */
    private static <T> boolean judgeByPredicateAnd(T t, Predicate<T> predicate1, Predicate<T> predicate2) {
        return predicate1.and(predicate2).test(t);
    }

    /**
     * 逻辑与
     * @param t
     * @param predicate1
     * @param predicate2
     * @param predicate3
     * @param <T>
     * @return
     */
    private static <T> boolean judgeByPredicateAnd2(T t, Predicate<T> predicate1, Predicate<T> predicate2, Predicate<T> predicate3) {
        return predicate1.and(predicate2).and(predicate3).test(t);
    }

    /**
     * 逻辑或
     * @param t
     * @param predicate1
     * @param predicate2
     * @param <T>
     * @return
     */
    private static <T> boolean judgeByPredicateOr(T t, Predicate<T> predicate1, Predicate<T> predicate2) {
        return predicate1.or(predicate2).test(t);
    }

    private static boolean judgeByPredicateEquals(String str1, String str2) {
        return Predicate.isEqual(str1).test(str2);
    }

    private static void test5() {
        // 逻辑与
        boolean judgeByPredicate = judgeByPredicateAnd("zhangsan", t -> t.length() > 5, t -> t.length() < 7);
        System.out.println("*and**"+judgeByPredicate);

        // 逻辑或
        boolean judgeByPredicateOr = judgeByPredicateOr("zhangsan", t -> t.length() > 5, t -> t.length() < 7);
        System.out.println("*or**"+judgeByPredicateOr);

        // 逻辑与2
        boolean judgeByPredicate4 = judgeByPredicateAnd2("zhangsan", t -> t.length() > 5, t -> t.length() < 10, t -> t.contains("li"));
        System.out.println("***"+judgeByPredicate4);

        // 是否存在
        boolean judgeByPredicate2 = judgeByPredicate(10,t -> t > 0);
        System.out.println(judgeByPredicate2);

        hashMap.put("zs", 18);
        hashMap.put("ls", 28);
        hashMap.put("ww", 38);
        boolean judgeByPredicate3 = judgeByPredicate("zs1", t -> hashMap.containsKey(t));
        System.out.println(judgeByPredicate3);
        System.out.println();
    }

    private static void test6() {
        String str1 = "zhangsan";
        String str2 = "zs";
        String str3 = "zhangsan";
        boolean judgeByPredicateEquals = judgeByPredicateEquals(str1, str2);
        System.out.println("judgeByPredicateEquals1: " + judgeByPredicateEquals);
        judgeByPredicateEquals = judgeByPredicateEquals(str1, str3);
        System.out.println("judgeByPredicateEquals2: " + judgeByPredicateEquals);
    }


}
